﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.DirectoryServices;
using Domain.ActiveDirectory.Model;
using System.Text.RegularExpressions;

namespace Domain.ActiveDirectory.Accessor
{
    public class UserAccessor : Accessor
    {
        public UserAccessor(Connection connection)
            : base(connection) { }

        private static IEnumerable<string> REQUIRED_PROPERTIES
            = new List<string>() { "cn", "samaccountname", "mail", "title", 
                "memberOf", "useraccountcontrol", "distinguishedName" };

        public IEnumerable<User> GetUsersByUsername(IEnumerable<string> usernames)
        {
            return FilterBy(new List<string>() { "samaccountname", "displayname", "sn" }, usernames);
        }

        public IEnumerable<User> GetUsersByCompleteName(IEnumerable<string> completeNames)
        {
            return FilterBy(new List<string>() { "cn" }, completeNames);
        }

        public IEnumerable<User> GetUsersByTitle(IEnumerable<string> titles)
        {
            return FilterBy(new List<string>() { "title" }, titles);
        }

        protected virtual IEnumerable<User> FilterBy(IEnumerable<string> propertyNames, IEnumerable<string> propertyValues)
        {
            string filterString = DetermineSearchString(propertyNames, propertyValues, 
                "(&(objectCategory=person)(objectClass=user)");
            _connection.Searcher.Filter = filterString.ToString();
            InitializePropertiesToLoad();
            SearchResultCollection usersFound = _connection.Searcher.FindAll();
            List<User> users = new List<User>();
            foreach (SearchResult result in usersFound)
            {
                var user = ConvertSearchResultToUser(result);
                users.Add(user);
            }
            return users.AsEnumerable();
        }

        private void InitializePropertiesToLoad()
        {
            _connection.Searcher.PropertiesToLoad.Clear();
            foreach (string propertyToLoad in REQUIRED_PROPERTIES)
            {
                _connection.Searcher.PropertiesToLoad.Add(propertyToLoad);
            }
        }

        private User ConvertSearchResultToUser(SearchResult searchResultUser)
        {
            User user = new User();
            if (searchResultUser != null)
            {
                user.CompleteName = searchResultUser.Properties["cn"][0].ToString();
                user.Username = searchResultUser.Properties["samaccountname"][0].ToString();
                user.Email = searchResultUser.Properties["mail"][0].ToString();
                user.Title = searchResultUser.Properties["title"][0].ToString();
                user.SetGroups(GetCommonNames(searchResultUser.Properties["memberOf"]));
                user.IsActive = (Convert.ToInt32(searchResultUser.Properties["useraccountcontrol"][0]) & 0x02) == 0;
                user.DistinguishedName = searchResultUser.Properties["distinguishedName"][0].ToString();
            }
            return user;
        }
    }
}
